home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1992 July / Nautilus-3-8 / Nautilus-3-8.bin / Tools & Utilities / Techy Stuff / Source ƒ / egrep-1.5 / grep-src / TransDisplay.c < prev    next >
Encoding:
Text File  |  1991-08-25  |  25.4 KB  |  1,113 lines

  1.  
  2. /*
  3.     TransDisplay version 2.0 - TransSkel plug-in module supporting
  4.     an arbitrary number of generic display windows with memory.
  5.  
  6.     TransSkel and TransDisplay are public domain, and are written by:
  7.  
  8.             Paul DuBois
  9.             Wisconsin Regional Primate Research Center
  10.             1220 Capitol Court
  11.             Madison, WI  53715-1299  USA
  12.  
  13.     UUCP:    {harvard,rutgers,ucbvax}!uwvax!rhesus!dubois
  14.     ARPA:    dubois@primate.wisc.edu
  15.  
  16.     This version of TransDisplay written for LightspeedC.  LightspeedC
  17.     is a trademark of:
  18.             THINK Technologies, Inc
  19.             420 Bedford Street  Suite 350
  20.             Lexington, MA  02173  USA
  21.  
  22.   History
  23.   08/25/86    Genesis.  Beta version.
  24.   09/15/86    Changed to allow arbitrary number of windows.  Changed
  25.             version number to 1.0.
  26.   01/17/87    Changed version number to 1.01.  The window type when a new
  27.             window is created with NewDWindow is documentProc+8 now, so
  28.             that the window will have a zoom box on a machine with 128K
  29.             ROMS.
  30.   01/29/89    Version 2.0.  Converted to work with TransSkel 2.0.  Display
  31.             window creation routines now check whether window and window
  32.             handler creation succeeded and return nil if not.  2-byte and
  33.             4-byte integer types are typedef'ed to Integer and Longint to
  34.             ease porting.
  35. */
  36.  
  37.  
  38. /*
  39.     The following symbol controls the compile mode.  If it is #define'd,
  40.     TransDisplay allows only a single display window, and generates
  41.     less code.  If it is #undef'ed, TransDisplay allows an arbitrary
  42.     number of display windows, but generates more code.
  43. */
  44.  
  45. # undef    singleDisplay
  46.  
  47. # include    <Controls.h>    /* includes WindowMgr.h, QuickDraw.h, MacTypes.h */
  48. # include    <TextEdit.h>
  49. #include <Memory.h>
  50. #include <Events.h>
  51. #include <Menus.h>
  52. #include <Memory.h>
  53. #include <Quickdraw.h>
  54. #include <Fonts.h>
  55. #include <Dialogs.h>
  56. #include <OSEvents.h>
  57. #include <ToolUtils.h>
  58. #include <Resources.h>
  59. #include "TransSkel.h"
  60. #include "TransDisplay.h"
  61.  
  62. /*
  63.     Display window types, constants, variables.
  64. */
  65.  
  66.  
  67. # define    monaco        4
  68.  
  69.  
  70. /*
  71.     Default values for display window characteristics
  72. */
  73.  
  74. static Integer    d_font = monaco;        /* default font              */
  75. static Integer    d_size = 9;                /* default pointsize         */
  76. static Integer    d_wrap = 0;                /* default word wrap (on)    */
  77. static Integer    d_just = teJustLeft;    /* default justification     */
  78. static Longint    d_maxText = 30000L;        /* default max text allowed  */
  79. static Longint    d_flushAmt = 25000L;    /* default autoflush amount  */
  80. static ProcPtr    d_activate = nil;        /* default notification proc */
  81.  
  82.  
  83. /*
  84.     Lowest allowable values for autoflush characteristics
  85. */
  86.  
  87. # define    d_loMaxText        (100L)
  88. # define    d_loFlushAmt    (100L)
  89.  
  90.  
  91. # ifndef    singleDisplay
  92.  
  93. /*
  94.     New(TypeName) returns handle to new object, for any TypeName.
  95.     If there is insufficient memory, the result is nil.
  96. */
  97.  
  98. # define    New(x)    (x **) NewHandle ((Size) sizeof (x))
  99.  
  100.  
  101. /*
  102.     dwList points to a list of structures describing the known display
  103.     windows.
  104.  
  105.     curDispWind is the current output window.
  106.     If curDispWind = nil, output is currently turned off.
  107. */
  108.  
  109.  
  110. typedef struct DisplayInfo
  111. {
  112.     WindowPtr            dWind;            /* display window         */
  113.     TEHandle            dTE;            /* window text            */
  114.     ControlHandle        dScroll;        /* window scroll bar      */
  115.     ProcPtr                dActivate;        /* notification procedure */
  116.     Longint                dMaxText;        /* max text length        */
  117.     Longint                dFlushAmt;        /* amount to autoflush    */
  118.     struct DisplayInfo    **dNext;        /* next window structure  */
  119. } DisplayInfo, *DIPtr, **DIHandle;
  120.  
  121.  
  122. static DIHandle        dwList = nil;
  123.  
  124. # endif
  125.  
  126. /*
  127.     Variables pertaining to the display window being operated on
  128.     (updated, resized, etc.).  This window is not necessarily the
  129.     same as curDispWind!  These variables are synced to the window
  130.     with SyncGlobals.
  131. */
  132.  
  133. # ifndef    singleDisplay
  134. static DIHandle            dispInfo;        /* info structure         */
  135. # endif
  136.  
  137. static DrawGrowBox(void);
  138. static DIHandle GetDInfo(WindowPtr theWind);
  139. static SyncGlobals(WindowPtr theWind);
  140. static CalcEditRect(Rect *r);
  141. static CalcScrollRect(Rect *r);
  142. static LinesOffTop(void);
  143. static HiliteScroll(void);
  144. static ScrollText(Integer lDelta);
  145. static pascal void TrackScroll(ControlHandle theScroll, Integer partCode);
  146. static OverhaulDisplay(void);
  147. static Activate(Boolean isActive);
  148. static Update(Boolean resized);
  149. static Mouse(Point thePt, Longint t, Integer mods);
  150. static Clobber(void);
  151. static SetupDWindow(void);
  152. static HexByte(Integer value);
  153.  
  154. static WindowPtr        dispWind = nil;    /* the window             */
  155. static TEHandle            dispTE;            /* window text            */
  156. static ControlHandle    dispScroll;        /* the scroll bar         */
  157. static ProcPtr            dActivate;        /* notification procedure */
  158. static Longint            dMaxText;        /* max text allowed       */
  159. static Longint            dFlushAmt;        /* amount to flush        */
  160.  
  161.  
  162. /*
  163.     curDispWind is the current output window.
  164.     If curDispWind = nil, output is turned off.
  165. */
  166.  
  167. static WindowPtr    curDispWind = nil;
  168.  
  169.  
  170. /* -------------------------------------------------------------------- */
  171. /*                Miscellaneous Internal (private) Routines                */
  172. /* -------------------------------------------------------------------- */
  173.  
  174.  
  175. /*
  176.     Draw grow box of dispWind in lower right hand corner
  177. */
  178.  
  179.  
  180. static DrawGrowBox (void)
  181. {
  182. register RgnHandle    oldClip;
  183. Rect                r;
  184.  
  185.     r = dispWind->portRect;
  186.     r.left = r.right - 15;        /* draw only in corner */
  187.     r.top = r.bottom - 15;
  188.     oldClip = NewRgn ();
  189.     GetClip (oldClip);
  190.     ClipRect (&r);
  191.     DrawGrowIcon (dispWind);
  192.     SetClip (oldClip);
  193.     DisposeRgn (oldClip);
  194. }
  195.  
  196.  
  197.  
  198. /* -------------------------------------------------------------------- */
  199. /*            Lowest-level Internal (Private) Display Window Routines        */
  200. /* -------------------------------------------------------------------- */
  201.  
  202.  
  203. # ifndef    singleDisplay
  204.  
  205. /*
  206.     Get display window info associated with window.
  207.     Return nil if window isn't a known display window.
  208. */
  209.  
  210. static DIHandle GetDInfo (WindowPtr theWind)
  211. {
  212. register DIHandle    h;
  213.  
  214.     for (h = dwList; h != nil; h = (**h).dNext)
  215.     {
  216.         if ((**h).dWind == theWind)
  217.             return (h);
  218.     }
  219.     return (nil);
  220. }
  221.  
  222. # endif
  223.  
  224. # ifdef    singleDisplay
  225. # define    SyncGlobals(x)    ;    /* make it a nop */
  226. # else
  227.  
  228. /*
  229.     Synchronize globals to a display window.  theWind must be a legal
  230.     display window, with one exception:  if theWind is nil, the
  231.     variables are synced to the current port.  That is safe (and
  232.     correct) because:
  233.     (i)     nil is only passed by display window handler procedures,
  234.          which are only called by TransSkel for display window
  235.          events.
  236.     (ii) For those handler procs that pass nil, TransSkel either sets
  237.          the port to the window before calling the proc (update, clobber,
  238.          idle procs), or the window is frontmost, and so will be the
  239.          current port anyway (mouse proc).
  240.     Hence, use of the current port under these circumstances
  241.     always produces a legal display window.
  242.     
  243.     SyncGlobals is not used in single display mode, because the
  244.     globals are all set by SetupDWindow and do not change thereafter.
  245. */
  246.  
  247. static SyncGlobals (WindowPtr theWind)
  248. {
  249. register DIPtr    dp;
  250.  
  251.     if (theWind == nil)                    /* use current window */
  252.         GetPort (&theWind);
  253.  
  254.     dispWind = theWind;
  255.     dispInfo = GetDInfo (dispWind);
  256.     dp = *dispInfo;
  257.     dispScroll = (*dp).dScroll;
  258.     dispTE = (*dp).dTE;
  259.     dActivate = (*dp).dActivate;
  260.     dMaxText = (*dp).dMaxText;
  261.     dFlushAmt = (*dp).dFlushAmt;
  262. }
  263.  
  264. # endif
  265.  
  266.  
  267. /*
  268.     Calculate the dimensions of the editing rectangle for
  269.     dispWind (which must be set properly and is assumed to be
  270.     the current port).  (The viewRect and destRect are the
  271.     same size.)  Assumes the port, text font and text size are all
  272.     set properly.  The viewRect is sized so that an integral
  273.     number of lines can be displayed in it, i.e., so that a
  274.     partial line never shows at the bottom.
  275. */
  276.  
  277. static CalcEditRect (Rect *r)
  278. {
  279. FontInfo            f;
  280. register Integer    lineHeight;
  281.  
  282.     GetFontInfo (&f);
  283.     lineHeight = f.ascent + f.descent + f.leading;
  284.     *r = dispWind->portRect;
  285.     r->left += 4;
  286.     r->right -= 17;            /* leave room for scroll bar + 2 */
  287.     r->top += 2;
  288.     r->bottom = r->top + ((r->bottom - r->top - 2) / lineHeight) * lineHeight;
  289. }
  290.  
  291.  
  292. /*
  293.     Calculate the dimensions of the scroll bar rectangle for the
  294.     window.  Make sure that the edges overlap the window frame and
  295.     the grow box.
  296. */
  297.  
  298. static CalcScrollRect (Rect *r)
  299. {
  300.     *r = dispWind->portRect;
  301.     ++r->right;
  302.     --r->top;
  303.     r->left = r->right - 16;
  304.     r->bottom -= 14;
  305. }
  306.  
  307.  
  308. /*
  309.     Calculate the number of lines currently scrolled off
  310.     the top.
  311. */
  312.  
  313. static LinesOffTop (void)
  314. {
  315. register TEPtr    ePtr;
  316.  
  317.     ePtr = *dispTE;
  318.     return (((*ePtr).viewRect.top - (*ePtr).destRect.top)
  319.                 / (*ePtr).lineHeight);
  320. }
  321.  
  322.  
  323. /*
  324.     Highlight the scroll bar properly.  This means that it's not
  325.     made active if the window itself isn't active, even if
  326.     there's enough text to fill the window.
  327. */
  328.  
  329. static HiliteScroll (void)
  330. {
  331.     HiliteControl (dispScroll, dispWind == FrontWindow () &&
  332.                                 GetCtlMax (dispScroll) > 0 ? 0 : 255);
  333. }
  334.  
  335.  
  336. /*
  337.     Scroll to the correct position.  lDelta is the
  338.     amount to CHANGE the current scroll setting by.
  339.     Positive scrolls the text up, negative down.
  340. */
  341.  
  342. static ScrollText (Integer lDelta)
  343. {
  344. register Integer    lHeight;
  345. register Integer    newLine;
  346. register Integer    topLine;
  347.  
  348.     lHeight = (**dispTE).lineHeight;
  349.     topLine = LinesOffTop ();
  350.     newLine = topLine + lDelta;
  351.     if (newLine < 0)
  352.         newLine = 0;
  353.     if (newLine > GetCtlMax (dispScroll))
  354.         newLine = GetCtlMax (dispScroll);
  355.     SetCtlValue (dispScroll, newLine);
  356.     TEScroll (0, (topLine - newLine ) * lHeight, dispTE);
  357. }
  358.  
  359.  
  360. /*
  361.     Filter proc for tracking mousedown in scroll bar.  The code for
  362.     the part originally hit is stored in the control's reference
  363.     value by Mouse () before calling this.
  364.  
  365.     Scroll by one line if the mouse is in an arrow.  Scroll by a half
  366.     window's worth of lines if the mouse is in a page region.
  367. */
  368.  
  369. static pascal void TrackScroll (ControlHandle theScroll, Integer partCode)
  370. {
  371. register Integer    lDelta;
  372. register Integer    halfPage;
  373.  
  374.     if (partCode == GetCRefCon (theScroll))    /* still in same part? */
  375.     {
  376.         halfPage = (((**dispTE).viewRect.bottom - (**dispTE).viewRect.top)
  377.                         / (**dispTE).lineHeight) / 2;
  378.         if (halfPage == 0)
  379.             ++halfPage;
  380.         switch (partCode)
  381.         {
  382.             case inUpButton: lDelta = -1; break;
  383.             case inDownButton: lDelta = 1; break;
  384.             case inPageUp: lDelta = -halfPage; break;
  385.             case inPageDown: lDelta = halfPage; break;
  386.         }
  387.         ScrollText (lDelta);
  388.     }
  389. }
  390.  
  391.  
  392. /*
  393.     Adjust the text in the text record and the scroll bar.  This is
  394.     called for major catastrophes, such as resizing the window, or
  395.     changing the word wrap style.  It makes sure the view and
  396.     destination rectangles are sized properly, and that the bottom
  397.     line of text never scrolls up past the bottom line of the
  398.     window, if there's enough to fill the window, and that the
  399.     scroll bar max and current values are set properly.
  400.  
  401.     Resizing the dest rect just means resetting the right edge
  402.     (the top is NOT reset), since text might be scrolled off the
  403.     top (i.e., destRect.top != 0).
  404. */
  405.  
  406. static OverhaulDisplay (void)
  407. {
  408. Rect                r;
  409. register Integer    nLines;            /* # of lines in TERec */
  410. register Integer    visLines;        /* # of lines displayable in window */
  411. register Integer    topLines;        /* # of lines currently scrolled off top */
  412. register Integer    scrollLines;    /* # of lines to scroll down */
  413. register Integer    lHeight;
  414.  
  415.     CalcEditRect (&r);
  416.     (**dispTE).destRect.right = r.right;
  417.     (**dispTE).viewRect = r;
  418.     TECalText (dispTE);        /* recalc line starts */
  419.     /*r = (**dispTE).viewRect;*/    /* ?? */
  420.     lHeight = (**dispTE).lineHeight;
  421.     nLines = (**dispTE).nLines;
  422.     visLines = (r.bottom - r.top) / lHeight;
  423.     topLines = LinesOffTop ();
  424.  
  425. /*
  426.     If the text doesn't fill the window (visLines > nLines - topLines),
  427.     pull the text down if possible (if topLines > 0).  Make sure not
  428.     to try to scroll down by more lines than are hidden off the top.
  429. */
  430.     scrollLines = visLines - (nLines - topLines);
  431.     if (scrollLines > 0 && topLines > 0)
  432.     {
  433.         if (scrollLines > topLines)
  434.             scrollLines = topLines;
  435.         TEScroll (0, scrollLines * lHeight, dispTE);
  436.         topLines -= scrollLines;
  437.     }
  438.     TEUpdate (&r, dispTE);
  439.  
  440.     SetCtlMax (dispScroll, nLines - visLines < 0 ? 0 : nLines - visLines);
  441.     SetCtlValue (dispScroll, topLines);
  442.     HiliteScroll ();
  443. }
  444.  
  445.  
  446. /* ---------------------------------------------------------------- */
  447. /*                        Window Handler Routines                        */
  448. /* ---------------------------------------------------------------- */
  449.  
  450.  
  451. /*
  452.     When the window comes active, highlight the scroll bar appropriately.
  453.     When the window is deactivated, un-highlight the scroll bar.
  454.     Redraw the grow box.
  455.  
  456.     Notify the host as appropriate.
  457.  
  458.     Note that clicking close box hides the window, which generates a
  459.     deactivate event, so there is no need for a close notifier.
  460. */
  461.  
  462. static Activate (Boolean isActive)
  463. {
  464.     SyncGlobals (nil);                /* sync to current port */
  465.     DrawGrowBox ();
  466.     HiliteScroll ();
  467.  
  468.     if (dActivate != nil)
  469.         ((void (*)(Boolean)) dActivate) (isActive);
  470. }
  471.  
  472.  
  473. /*
  474.     Update window.  The update event might be in response to a
  475.     window resizing.  If so, move and resize the scroll bar,
  476.     and recalculate the text display.
  477.  
  478.     The ValidRect call is done because the HideControl adds the
  479.     control bounds box to the update region - which would generate
  480.     another update event!  Since everything is redrawn below anyway,
  481.     the ValidRect is used to cancel the update.
  482. */
  483.  
  484. static Update (Boolean resized)
  485. {
  486. Rect    r;
  487.  
  488.     SyncGlobals (nil);                    /* sync to current port */
  489.     r = dispWind->portRect;
  490.     EraseRect (&r);
  491.     if (resized)
  492.     {
  493.         HideControl (dispScroll);
  494.         r = (**dispScroll).contrlRect;
  495.         ValidRect (&r);
  496.         CalcScrollRect (&r);
  497.         SizeControl (dispScroll, 16, r.bottom - r.top);
  498.         MoveControl (dispScroll, r.left, r.top);
  499.         OverhaulDisplay ();
  500.         ShowControl (dispScroll);
  501.     }
  502.     else
  503.     {
  504.         r = (**dispTE).viewRect;
  505.         TEUpdate (&r, dispTE);        /* redraw text display */
  506.     }
  507.  
  508.     DrawGrowBox ();
  509.     DrawControls (dispWind);    /* redraw scroll bar */
  510. }
  511.  
  512.  
  513. /*
  514.     Handle mouse clicks in window
  515. */
  516.  
  517. static Mouse (Point thePt, Longint t, Integer mods)
  518. {
  519. register Integer    thePart;
  520. register Integer    oldCtlValue;
  521.  
  522.     SyncGlobals (nil);                /* sync to current port */
  523.  
  524.     if ((thePart = TestControl (dispScroll, thePt)) == inThumb)
  525.     {
  526.         oldCtlValue = GetCtlValue (dispScroll);
  527.         if (TrackControl (dispScroll, thePt, nil) == inThumb)
  528.             ScrollText (GetCtlValue (dispScroll) - oldCtlValue);
  529.     }
  530.     else if (thePart != 0)
  531.     {
  532.         SetCRefCon (dispScroll, (Longint) thePart);
  533.         (void) TrackControl (dispScroll, thePt, &TrackScroll);
  534.     }
  535. }
  536.  
  537.  
  538.  
  539. /*
  540.     Remove the display window from the list, and dispose of it.
  541.     Since the clobber procedure is never called except for real display
  542.     windows, and since the list must therefore be non-empty, it is
  543.     not necessary to check the legality of the window or that the
  544.     window's in the list.
  545.  
  546.     Must do SetDWindow (nil) to turn output off, if the window being
  547.     clobbered is the current output window.
  548. */
  549.  
  550. static Clobber (void)
  551. {
  552. # ifndef    singleDisplay
  553. register DIHandle    h, h2;
  554. # endif
  555.  
  556.     SyncGlobals (nil);                    /* sync to current port */
  557.  
  558.     if (dispWind == curDispWind)
  559.         SetDWindow (nil);
  560.  
  561. # ifndef    singleDisplay
  562.  
  563.     if ((**dwList).dWind == dispWind)    /* is it the first window in list? */
  564.     {
  565.         h2 = dwList;
  566.         dwList = (**dwList).dNext;
  567.     }
  568.     else
  569.     {
  570.         for (h = dwList; h != nil; h = h2)
  571.         {
  572.             h2 = (**h).dNext;
  573.             if ((**h2).dWind == dispWind)    /* found it */
  574.             {
  575.                 (**h).dNext = (**h2).dNext;
  576.                 break;
  577.             }
  578.         }
  579.     }
  580.     DisposHandle ((Handle)h2);        /* get rid of information structure */
  581.  
  582. # endif
  583.  
  584.     TEDispose (dispTE);            /* toss text record */
  585.     DisposeWindow (dispWind);    /* toss window and scroll bar */
  586.     dispWind = nil;
  587. }
  588.  
  589.  
  590. /* ---------------------------------------------------------------- */
  591. /*                            Control Routines                        */
  592. /* ---------------------------------------------------------------- */
  593.  
  594.  
  595. /*
  596.     Test whether a window is a legal display window or not
  597. */
  598.  
  599. Boolean IsDWindow (WindowPtr theWind)
  600. {
  601.  
  602. # ifdef    singleDisplay
  603.     return (theWind == dispWind && dispWind != nil);
  604. # else
  605.     return (GetDInfo (theWind) != nil);
  606. # endif
  607. }
  608.  
  609.  
  610. /*
  611.     Return handle to display window's text record
  612. */
  613.  
  614. TEHandle GetDWindowTE (WindowPtr theWind)
  615. {
  616.  
  617. # ifndef    singleDisplay
  618. register DIHandle    dInfo;
  619.     return (GetDInfo (theWind) == nil ? nil : (**dInfo).dTE);
  620. # else
  621.     return (IsDWindow (theWind) ? dispTE : nil);
  622. # endif
  623. }
  624.  
  625.  
  626. /*
  627.     Change the text display characteristics of a display window
  628.     and redisplay it.  As a side effect, this always scrolls to the
  629.     home position.
  630. */
  631.  
  632. SetDWindowStyle (WindowPtr theWind, Integer font, Integer size, Integer wrap, Integer just)
  633. {
  634. GrafPtr                savePort;
  635. FontInfo            f;
  636. register TEHandle    te;
  637. Rect                r;
  638.  
  639.     if (theWind == nil)            /* reset window creation defaults */
  640.     {
  641.         d_font = font;
  642.         d_size = size;
  643.         d_wrap = wrap;
  644.         d_just = just;
  645.         return;
  646.     }
  647.  
  648.     if (IsDWindow (theWind))
  649.     {
  650.         GetPort (&savePort);
  651.         SyncGlobals (theWind);
  652.         SetPort (dispWind);
  653.         te = dispTE;
  654.         r = (**te).viewRect;
  655.         EraseRect (&r);
  656.         r = (**te).destRect;    /* scroll home without redrawing */
  657.         OffsetRect (&r, 0, 2 - r.top);
  658.         (**te).destRect = r;
  659.  
  660.         (**te).crOnly = wrap;    /* set word wrap */
  661.         TESetJust (just, te);    /* set justification */
  662.  
  663.         TextFont (font);         /* set the font and point size */
  664.         TextSize (size);        /* of text record (this is the */
  665.         GetFontInfo (&f);        /* hard part) */
  666.         (**te).lineHeight = f.ascent + f.descent + f.leading;
  667.         (**te).fontAscent = f.ascent;
  668.         (**te).txFont = font;
  669.         (**te).txSize = size;
  670.  
  671.         OverhaulDisplay ();
  672.         SetPort (savePort);
  673.     }
  674. }
  675.  
  676.  
  677. /*
  678.     Scroll the text in the window so that line lineNum is at the top.
  679.     First line is line zero.
  680. */
  681.  
  682. SetDWindowPos (WindowPtr theWind, Integer lineNum)
  683. {
  684. GrafPtr        savePort;
  685.  
  686.     if (IsDWindow (theWind))
  687.     {
  688.         GetPort (&savePort);
  689.         SyncGlobals (theWind);
  690.         SetPort (dispWind);
  691.         ScrollText (lineNum - GetCtlValue (dispScroll));
  692.         SetPort (savePort);
  693.     }
  694. }
  695.  
  696.  
  697. /*
  698.     Set display window activate notification procedure.
  699.     Pass nil to disable it.
  700. */
  701.  
  702. SetDWindowNotify (WindowPtr theWind, ProcPtr p)
  703. {
  704. # ifndef    singleDisplay
  705. register DIHandle    dInfo;
  706. # endif
  707.  
  708.     if (theWind == nil)            /* reset window creation default */
  709.     {
  710.         d_activate = p;
  711.         return;
  712.     }
  713.  
  714. # ifdef    singleDisplay
  715.  
  716.     if (IsDWindow (theWind))
  717.         dActivate = p;
  718.  
  719. # else
  720.  
  721.     if ((dInfo = GetDInfo (theWind)) != nil)
  722.     {
  723.         (**dInfo).dActivate = p;
  724.     }
  725.  
  726. # endif
  727. }
  728.  
  729.  
  730. /*
  731.     Set display window autoflush characteristics
  732. */
  733.  
  734. SetDWindowFlush (WindowPtr theWind, Longint maxText, Longint flushAmt)
  735. {
  736. # ifndef    singleDisplay
  737. register DIHandle    dInfo;
  738. # endif
  739.  
  740.     if (maxText > 32767L)
  741.         maxText = 32767L;
  742.     if (maxText < d_loMaxText)
  743.         maxText = d_loMaxText;
  744.     if (flushAmt < d_loFlushAmt)
  745.         flushAmt = d_loFlushAmt;
  746.  
  747.     if (theWind == nil)            /* reset window creation defaults */
  748.     {
  749.         d_maxText = maxText;
  750.         d_flushAmt = flushAmt;
  751.         return;
  752.     }
  753.  
  754. # ifdef    singleDisplay
  755.  
  756.     if (IsDWindow (theWind))
  757.     {
  758.  
  759.         dMaxText = maxText;
  760.         dFlushAmt = flushAmt;
  761.     }
  762.  
  763. # else
  764.  
  765.     if ((dInfo = GetDInfo (theWind)) != nil)
  766.     {
  767.         (**dInfo).dMaxText = maxText;
  768.         (**dInfo).dFlushAmt = flushAmt;
  769.     }
  770.  
  771. # endif
  772. }
  773.  
  774.  
  775. /*
  776.     Set which display window is to be used for output.  If theWind
  777.     is nil, output is turned off.  If theWind is not a legal display
  778.     window, nothing is done.
  779. */
  780.  
  781. SetDWindow (WindowPtr theWind)
  782. {
  783.     if (theWind == nil || IsDWindow (theWind))
  784.     {
  785.         curDispWind = theWind;
  786.     }
  787. }
  788.  
  789.  
  790. /*
  791.     Get the WindowPtr of the current output display window.  If
  792.     output is turned off, this will be nil.
  793. */
  794.  
  795. GetDWindow (WindowPtr *theWind)
  796. {
  797.     *theWind = curDispWind;
  798. }
  799.  
  800.  
  801. /*
  802.     Flush text from the window and readjust the display.
  803. */
  804.  
  805. FlushDWindow (WindowPtr theWind, Longint byteCount)
  806. {
  807.     if (IsDWindow (theWind))
  808.     {
  809.         SyncGlobals (theWind);
  810.         TESetSelect (0L, byteCount, dispTE);    /* select text */
  811.         TEDelete (dispTE);                        /* clobber it */
  812.         OverhaulDisplay ();
  813.     }
  814. }
  815.  
  816.  
  817. /*
  818.     Create and initialize a display window and the associated data
  819.     structures, and return the window pointer.  Install window in
  820.     list of display windows.
  821. */
  822.  
  823. static SetupDWindow (void)
  824. {
  825. Rect    r;
  826. GrafPtr    savePort;
  827.  
  828. # ifndef    singleDisplay
  829. register DIHandle    dInfo;
  830. # endif
  831.  
  832.  
  833.     GetPort (&savePort);
  834.     if (SkelWindow (dispWind,    /* the window */
  835.                 Mouse,        /* mouse click handler */
  836.                 nil,        /* key clicks are ignored */
  837.                 Update,        /* window updating procedure */
  838.                 Activate,    /* window activate/deactivate procedure */
  839.                 nil,        /* TransSkel hides window if no close proc */
  840.                             /* (generates deactivate event) */
  841.                 Clobber,    /* window disposal procedure */
  842.                 nil,        /* no idle proc */
  843.                 false) == 0)    /* irrelevant since no idle proc */
  844.     {
  845.         SetPort (savePort);
  846.         return (0);
  847.     }
  848.  
  849. /*
  850.     Build the scroll bar.  Make sure the borders overlap the
  851.     window frame and the frame of the grow box.
  852. */
  853.  
  854.     CalcScrollRect (&r);
  855.     dispScroll = NewControl (dispWind, &r, "\p", true, 0, 0, 0,
  856.                                 scrollBarProc, 0L);
  857.  
  858. /*
  859.     Create the TE record used for text display.  Use defaults for
  860.     display characteristics.  Setting window style overhauls
  861.     display, so can cancel and update event pending for the window.
  862. */
  863.  
  864.     CalcEditRect (&r);
  865.     dispTE = TENew (&r, &r);
  866.  
  867. # ifndef    singleDisplay
  868.  
  869. /*
  870.     Get new information structure, attach to list of known display
  871.     windows.
  872. */
  873.     dInfo = New (DisplayInfo);
  874.     (**dInfo).dNext = dwList;
  875.     dwList = dInfo;
  876.     (**dInfo).dWind = dispWind;
  877.     (**dInfo).dScroll = dispScroll;
  878.     (**dInfo).dTE = dispTE;
  879.     
  880. # endif
  881.  
  882.     SetDWindowNotify (dispWind, d_activate);
  883.     SetDWindowFlush (dispWind, d_maxText, d_flushAmt);
  884.     SetDWindowStyle (dispWind, d_font, d_size, d_wrap, d_just);
  885.  
  886. /*
  887.     Make window current display output window
  888. */
  889.  
  890.     SetDWindow (dispWind);
  891.     SetPort (savePort);
  892.     return (1);
  893. }
  894.  
  895.  
  896. /*
  897.     Create and initialize a display window and the associated data
  898.     structures, and return the window pointer.  Install window in
  899.     list of display windows.  In single-window mode, disallow
  900.     creation of a new window if one already exists.
  901.  
  902.     The parameters are similar to those for NewWindow.  See Inside
  903.     Macintosh.
  904. */
  905.  
  906. WindowPtr NewDWindow (Rect *bounds, StringPtr title, Boolean visible, WindowPtr behind, Boolean goAway, Longint refCon)
  907. {
  908.  
  909. # ifdef    singleDisplay
  910.  
  911.     if (dispWind != nil)
  912.         return (nil);
  913.  
  914. # endif
  915.  
  916.     if ((dispWind = NewWindow (nil,
  917.                                bounds,
  918.                                title,
  919.                                visible,
  920.                                documentProc + 8,
  921.                                behind,
  922.                                goAway,
  923.                                refCon)) != nil)
  924.     {
  925.         if (SetupDWindow ())
  926.             return (dispWind);
  927.         DisposeWindow (dispWind);
  928.     }
  929.     return (nil);
  930. }
  931.  
  932.  
  933. /*
  934.     Create and initialize a display window (using a resource) and
  935.     the associated data structures, and return the window pointer.
  936.     Install window in list of display windows.  In single-window
  937.     mode, disallow creation of a new window if one already exists.
  938.  
  939.     The parameters are similar to those for GetNewWindow.  See Inside
  940.     Macintosh.
  941. */
  942.  
  943. WindowPtr GetNewDWindow (Integer resourceNum, WindowPtr behind)
  944. {
  945.  
  946. # ifdef    singleDisplay
  947.  
  948.     if (dispWind != nil)
  949.         return (nil);
  950.  
  951. # endif
  952.  
  953.     if ((dispWind = GetNewWindow (resourceNum, nil, behind)) != nil)
  954.     {
  955.         if (SetupDWindow ())
  956.             return (dispWind);
  957.         DisposeWindow (dispWind);
  958.     }
  959.     return (nil);
  960. }
  961.  
  962.  
  963.  
  964.  
  965. /* ------------------------------------------------------------ */
  966. /*                        Output Routines                            */
  967. /* ------------------------------------------------------------ */
  968.  
  969.  
  970. /*
  971.     Write text to display area if output is on (curDispWind != nil).
  972.     DisplayText is the fundamental output routine.  All other
  973.     output calls map (eventually) to it.
  974.  
  975.     First check whether the insertion will cause overflow and flush
  976.     out some stuff if so.  Insert new text at the end, then test
  977.     whether lines must be scrolled to get the new stuff to show up.
  978.     If yes, then do the scroll.  Set values of scroll bar properly
  979.     and highlight as appropriate.
  980.  
  981.     The current port is preserved.  Since all output calls end up
  982.     here, it's the only output routine that has to save the port
  983.     and check whether output is on.
  984. */
  985.  
  986. DisplayText (Ptr theText, Longint len)
  987. {
  988. register Integer    nLines;            /* # of lines in TERec */
  989. register Integer    dispLines;        /* # of lines displayable in window */
  990. register Integer    topLines;        /* # of lines currently scrolled off top */
  991. register Integer    scrollLines;    /* # of lines to scroll up */
  992. register Integer    lHeight;
  993. Rect                r;
  994. GrafPtr                savePort;
  995. register TEHandle    dTE;
  996.  
  997.     if (curDispWind == nil)
  998.         return;
  999.  
  1000.     GetPort (&savePort);
  1001.     SetPort (curDispWind);
  1002.     SyncGlobals (curDispWind);
  1003.     dTE = dispTE;
  1004.  
  1005.     if ((**dTE).teLength + len > dMaxText)    /* check overflow */
  1006.     {
  1007.         FlushDWindow (dispWind, dFlushAmt);
  1008.         DisplayString ("\p\r(autoflush occurred)\r");
  1009.     }
  1010.  
  1011.     lHeight = (**dTE).lineHeight;
  1012.     TESetSelect (32767L, 32767L, dTE);    /* set to insert at end */
  1013.     TEInsert (theText, len, dTE);
  1014.     r = (**dTE).viewRect;
  1015.     nLines = (**dTE).nLines;
  1016.     dispLines = (r.bottom - r.top) / lHeight;
  1017.     topLines = LinesOffTop ();
  1018.     scrollLines = nLines - (topLines + dispLines);
  1019.     if (scrollLines > 0) /* must scroll up */
  1020.         TEScroll (0, -lHeight * scrollLines, dTE); /* scroll up */
  1021.     topLines = nLines - dispLines;
  1022.     if (topLines >= 0 && GetCtlMax (dispScroll) != topLines)
  1023.     {
  1024.         SetCtlMax (dispScroll, topLines);
  1025.         SetCtlValue (dispScroll, topLines);
  1026.     }
  1027.     HiliteScroll ();
  1028.     SetPort (savePort);
  1029. }
  1030.  
  1031.  
  1032. /*
  1033.     Derived output routines:
  1034.  
  1035.     DisplayString    Write (Pascal) string
  1036.  
  1037.     DisplayLong        Write value of long integer
  1038.     DisplayInt        Write value of integer
  1039.     DisplayChar        Write character
  1040.  
  1041.     DisplayHexLong    Write value of long integer in hex (8 digits)
  1042.     DisplayHexInt    Write value of integer in hex (4 digits)
  1043.     DisplayHexChar    Write value of character in hex (2 digit)
  1044.  
  1045.     DisplayBoolean    Write boolean value
  1046.     DisplayLn        Write carriage return
  1047. */
  1048.  
  1049. DisplayString (StringPtr theStr)
  1050. {
  1051.     DisplayText ((void *)(theStr+1), (Longint) theStr[0]);
  1052. }
  1053.  
  1054.  
  1055. DisplayLong (Longint l)
  1056. {
  1057. Str255        s;
  1058.  
  1059.     NumToString (l, s);
  1060.     DisplayString (s);
  1061. }
  1062.  
  1063.  
  1064. DisplayInt (Integer i)
  1065. {
  1066.     DisplayLong ((Longint) i);
  1067. }
  1068.  
  1069.  
  1070. DisplayChar (char c)
  1071. {
  1072.     DisplayText (&c, 1L);
  1073. }
  1074.  
  1075.  
  1076. DisplayLn (void)
  1077. {
  1078.     DisplayChar ('\r');
  1079. }
  1080.  
  1081.  
  1082. DisplayBoolean (Boolean b)
  1083. {
  1084.     DisplayString (b ? "\ptrue" : "\pfalse");
  1085. }
  1086.  
  1087.  
  1088. static HexByte (Integer value)
  1089. {
  1090.     DisplayChar ((char) (value + (value < 10 ? '0' : 'a' - 10)));
  1091. }
  1092.  
  1093.  
  1094. DisplayHexChar (char c)
  1095. {
  1096.     HexByte ((Integer) (c >> 4) & 0x0f);
  1097.     HexByte ((Integer) c & 0x0f);
  1098. }
  1099.  
  1100.  
  1101. DisplayHexInt (Integer i)
  1102. {
  1103.     DisplayHexChar ((char) ((i >> 8) & 0xff));
  1104.     DisplayHexChar ((char) (i & 0xff));
  1105. }
  1106.  
  1107.  
  1108. DisplayHexLong (Longint l)
  1109. {
  1110.     DisplayHexInt ((Integer) (l >> 16) & 0xffff);
  1111.     DisplayHexInt ((Integer) l & 0xffff);
  1112. }
  1113.